﻿Imports System.Collections.ObjectModel
Imports FuncClasses.Bn.Classes
Imports System.Threading.Tasks
Imports System.Windows.Threading

Public Class UpdateProvider
    Public Event Update(ByVal oldfile As UpdateFileInfo, ByVal newversion As Decimal)
    Public Event CloseApplication()
    Public Event ReloadAddins()
    Public Event Updated(file As UpdateFileInfo)
    Public Event NoUpdate(file As UpdateFileInfo)
    Private list As New Collection(Of UpdateFileInfo)
    WithEvents xd As New Xml.XmlDocument
    WithEvents downloader As New FileDownloader
    Private downloadfilenname As String = ""
    Private restart As Boolean = False
    Private updatedfile As UpdateFileInfo
    Private dispatcher As Windows.Threading.Dispatcher

    Public Sub New(_dispatcher As Windows.Threading.Dispatcher)
        dispatcher = _dispatcher
        AddFile(New UpdateFileInfo("FuncClasses.dll", "Funktionsbibliothek", 1.52))
        LoadUpdateXML()
    End Sub

    Public Sub AddFile(ByVal file As UpdateFileInfo)
        list.Add(file)
        Task.Factory.StartNew(AddressOf CheckforUpdates)
    End Sub

    Private Sub CheckforUpdates()
        Dim waiting As Integer = 0
        Do While xd.DocumentElement Is Nothing AndAlso waiting < 30
            Threading.Thread.Sleep(1000)
            waiting += 1
        Loop
        If waiting <> 30 Then
            CompareVersions()
        End If
    End Sub

    Public Sub InstallUpdate(ByVal file As UpdateFileInfo, Optional ByVal Progressbar As System.Windows.Controls.ProgressBar = Nothing)
        Try
            Dim Node As Xml.XmlNode = xd.DocumentElement.SelectSingleNode( _
                                                          "/biller/update/file[@filename=""" & file.Filename & """]")
            Dim fileinfo As New FileDownloader.FileInfo(Node.Attributes.GetNamedItem("updatesource").Value.ToString)
            restart = CBool(Node.Attributes.GetNamedItem("requiresrestart").Value)
            downloadfilenname = fileinfo.Name
            downloader.Files.Clear()
            downloader.Files.Add(fileinfo)
            downloader.LocalDirectory = My.Computer.FileSystem.SpecialDirectories.Temp
            _progressbar = Progressbar
            updatedfile = file
            downloader.Start()
        Catch : End Try
    End Sub

    Private _progressbar As System.Windows.Controls.ProgressBar
    Private Sub downloader_progress() Handles downloader.ProgressChanged
        If _progressbar IsNot Nothing Then
            _progressbar.Value = downloader.CurrentFilePercentage()
        End If
    End Sub

    Private Sub downloader_StateChanged() Handles downloader.StateChanged
        If downloader.IsBusy = False Then
            'Start Update
            If restart Then
                Dim p As New Process
                p.StartInfo.FileName = My.Computer.FileSystem.SpecialDirectories.Temp + "\" + downloadfilenname
                p.StartInfo.Arguments = "/D=" + System.AppDomain.CurrentDomain.BaseDirectory()
                p.Start()
                RaiseEvent CloseApplication()
            Else
                'Make quiet installation
                _progressbar.IsIndeterminate = True
                Dim p As New Process
                p.StartInfo.FileName = My.Computer.FileSystem.SpecialDirectories.Temp + "\" + downloadfilenname
                p.StartInfo.Arguments = "/S /D=" + System.AppDomain.CurrentDomain.BaseDirectory()
                p.Start()
                p.WaitForExit()
                Try
                    IO.File.Delete(My.Computer.FileSystem.SpecialDirectories.Temp + "\" + downloadfilenname)
                Catch ex As Exception : End Try

                _progressbar.IsIndeterminate = False
                _progressbar.Value = 100

                RaiseEvent Updated(updatedfile)
                RaiseEvent ReloadAddins()
            End If
        End If
    End Sub

    Private Sub CompareVersions()
        Try
            For Each file As UpdateFileInfo In list
                Dim Node As Xml.XmlNode = xd.DocumentElement.SelectSingleNode( _
                                                                  "/biller/update/file[@filename=""" & file.Filename & """]")
                If Node IsNot Nothing Then
                    Dim nver As Decimal = CDec(Node.Attributes.GetNamedItem("version").Value.Replace(".", ","))
                    If nver > file.FileVersion Then
                        file.SetFileVersion(nver)
                        file.SetRestart(CBool(Node.Attributes.GetNamedItem("requiresrestart").Value))
                        If Node.Attributes.GetNamedItem("infodescr") IsNot Nothing Then
                            file.SetInfoDescrp(Node.Attributes.GetNamedItem("infodescr").Value)
                        End If
                        dispatcher.BeginInvoke(DispatcherPriority.Send, Sub()
                                                                            RaiseEvent Update(file, Node.Attributes.GetNamedItem("version").Value.Replace(".", ","))
                                                                        End Sub)
                    Else
                        dispatcher.BeginInvoke(DispatcherPriority.Send, Sub()
                                                                            RaiseEvent NoUpdate(file)
                                                                        End Sub)
                    End If
                End If
            Next
        Catch ex As Exception
            Log.AddError(ex.ToString)
        End Try
    End Sub

#Region "XML"
    Private Sub LoadUpdateXML()
        Dim task As task = task.Factory.StartNew(Sub()
                                                     Try
                                                         xd.Load("http://www.lastelb.com/biller/update/updateinfo.xml")
                                                         dispatcher.BeginInvoke(Sub()
                                                                                    CompareVersions()
                                                                                End Sub)
                                                     Catch ex As Exception : End Try
                                                 End Sub)
    End Sub
#End Region
End Class

Public Class UpdateFileInfo
    Private _filename As String
    Private _bezeichnung As String
    Private _fileversion As Decimal
    Private _infodescr As String
    Private _restart As Boolean

    Public Sub New(ByVal Filename As String, Bezeichnung As String, Version As Decimal, Optional infodescr As String = "", Optional ByVal restart As Boolean = False)
        _filename = Filename
        _bezeichnung = Bezeichnung
        _fileversion = Version
        _infodescr = infodescr
        _restart = restart
    End Sub

    Public ReadOnly Property InfoDescription As String
        Get
            Return _infodescr
        End Get
    End Property


    Public ReadOnly Property Filename As String
        Get
            Return _filename
        End Get
    End Property

    ''' <summary>
    ''' Returns the Name of the Programmpart (e.g. the Layoutname or Pluginname)
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Description As String
        Get
            Return _bezeichnung
        End Get
    End Property

    Public ReadOnly Property FileVersion As Decimal
        Get
            Return _fileversion
        End Get
    End Property

    Public Sub SetFileVersion(newVersion As Decimal)
        _fileversion = newVersion
    End Sub

    Public Sub SetInfoDescrp(text As String)
        _infodescr = text
    End Sub

    Public Sub SetRestart(value As Boolean)
        _restart = value
    End Sub

    Public ReadOnly Property RequiresRestart As Boolean
        Get
            Return _restart
        End Get
    End Property

    Public Overrides Function Equals(obj As Object) As Boolean
        Try
            Dim item As UpdateFileInfo = obj
            If item.Filename = Filename Then
                Return True
            End If
            Return False
        Catch ex As Exception
            Return False
        End Try
    End Function
End Class
